package main
import (
  "time"
  "fmt"
  "os"
  "io"
  "log"
  "path"
  "context"
  "os/exec"
  "bufio"
)

const RTMP_LOG_PATH = "./rtmp_log"

type RTMP2RTC struct {
    Url   string  `json:"url"`
    Liveid string  `json:"liveid"`
    Start time.Time `json:"start_time"`
    State   string `json:"status"`
    logOutput   *log.Logger
    logFile    *os.File
    //defer rtmp2rtc.logFile.Close()
    //DON'T forget close
    ctx context.Context
    cancel context.CancelFunc
}

func (rtmp2rtc *RTMP2RTC) Close(){
    if rtmp2rtc == nil {
        return
    }
    rtmp2rtc.cancel()
}

func Worker(rtmp_url string, liveid string, start time.Time)(*RTMP2RTC){
    var rtmp2rtc RTMP2RTC
    var err error

    rtmp2rtc.Url = rtmp_url
    rtmp2rtc.Liveid = liveid
    if start.IsZero() {
        rtmp2rtc.Start = time.Now()
    }else {
        rtmp2rtc.Start = start
    }
    rtmp2rtc.State = "inited"

    logfile := path.Join(RTMP_LOG_PATH, liveid)
    if _, err := os.Stat(RTMP_LOG_PATH); os.IsNotExist(err) {
        os.Mkdir(RTMP_LOG_PATH, os.ModePerm)
    }
    rtmp2rtc.logFile, err  = os.OpenFile(logfile, os.O_CREATE | os.O_WRONLY | os.O_APPEND, 0666)
    //defer rtmp2rtc.logFile.Close()
    if err != nil {
        log.Fatalln("open file error !")
    }
    rtmp2rtc.logOutput = log.New(rtmp2rtc.logFile, "", log.Lshortfile | log.Ltime)
    rtmp2rtc.logOutput.Println("Liveid:", liveid, "Started")

    rtmp2rtc.ctx, rtmp2rtc.cancel = context.WithCancel(context.Background())
    fmt.Printf("%+v\n", rtmp2rtc)
    go doStuff(&rtmp2rtc)
    return &rtmp2rtc
}

func doStuff(rtmp2rtc * RTMP2RTC) {
    rtmp2rtc.State = "running"
    //cmd := exec.CommandContext(rtmp2rtc.ctx, "./v2rtmp_h264", "-t", "bf0975031ef74472ae13022e5b77e8ac",
    //                 "-c", rtmp2rtc.Liveid, "-r", rtmp2rtc.Url)
    cmd := exec.CommandContext(rtmp2rtc.ctx, "./rtmp2rtmp", rtmp2rtc.Url)
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println(err)
    }
    defer stdout.Close()

    if err := cmd.Start(); err != nil{
        fmt.Println(err)
    }
    nodata := 0
    input := make(chan int, 1)
    go func (input chan int, stdout io.Reader){
        br := bufio.NewReaderSize(stdout, 128)
        for {
            w, _, err := br.ReadLine()
            if err != nil {
                 break
            }
            if len(w) > 0 {
                input <- 1
                rtmp2rtc.logOutput.Println(string(w))
            }
        }
    }(input, stdout)
LOOP:
    for {
        select {
            //timeout
            case <- rtmp2rtc.ctx.Done(): {
                break LOOP
            }
            default:
        }

        select {
            case <-input:
                nodata = 0
            case <-time.After(2 * time.Second):
                nodata += 1
                if nodata >= 6 {
                    rtmp2rtc.State = "nodata"
                    fmt.Println("timed out")
                }
        }
    }

    cmd.Wait()
    rtmp2rtc.logOutput.Println("Liveid: ", rtmp2rtc.Url, "Exited")
    rtmp2rtc.logFile.Close()
}


func bmain(){

     r := Worker("rtmp://localhost/2/ab", "eadfadf", time.Now())
     fmt.Println(r)
     for {
         time.Sleep(1 * time.Second)
        // r.cancel()
     }
}
